package cn.zaichi.edu.excelcommon.utils.impl;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.zaichi.edu.excelcommon.annotations.ExcelDynamicValue;
import cn.zaichi.edu.excelcommon.annotations.ExcelField;
import cn.zaichi.edu.excelcommon.entity.BaseExportParam;
import cn.zaichi.edu.excelcommon.entity.ExcelRegionVo;
import cn.zaichi.edu.excelcommon.entity.ExportTitleEntity;
import cn.zaichi.edu.excelcommon.plugs.convertor.VoidConvertor;
import cn.zaichi.edu.excelcommon.utils.ExcelExport;
import cn.zaichi.edu.excelcommon.utils.ExportTitleUtil;
import cn.zaichi.edu.excelcommon.utils.ExportWorkbookUtil;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;

/**
 * 使用 bean 方式导出excel 工具类
 *
 *
 *     //有表头列表的，分析表头列表，生成表头，没有表头列表根据实体标记的表头生成简单表头
 *     //非模板导出情况下--表格样式：有传入样式的，使用自定义样式，否则使用默认样式
 *     //模板导出不添加样式
 *     //数据不能合并列
 *     //表头合并列是使用传入表头的上级关系分析得来
 *     //创建表格 或者读取 模板表格
 *     //创建sheet 或者读取模板sheet
 *     //分析表头
 *     //设置表头样式
 *     //创建表头
 *     //添加数据
 *     //添加数据样式 规则同表头样式
 *     //数据合并行
 */
public class ExcelBeanExportUtil implements ExcelExport {

    BaseExportParam param;
    Workbook workbook;
    HSSFSheet sheet;
    List<ExportTitleEntity> titleEntityList=new ArrayList<>();
    List<?> dataList;

    List<ExcelRegionVo> regionVoList=new ArrayList<>();

    /**
     * 初始化
     * @param param
     * @throws IOException
     * @throws GeneralSecurityException
     */
    public ExcelBeanExportUtil(BaseExportParam param) throws IOException, GeneralSecurityException, IllegalAccessException {
        this.param=param;
        //获取表格
        this.workbook=ExportWorkbookUtil.getWorkbook(param);
        this.sheet=ExportWorkbookUtil.getSheet(param,workbook);
        this.dataList=param.getDataList();
        //设置表头数据
        setTitleEntityList();
        //创建表头
        ExportTitleUtil.setSheetTitle(param.getTitleStarRow(),titleEntityList,sheet,param,workbook);
        //设置数据
        setData();
    }




    /**
     * 设置表头List
     * @throws IllegalAccessException
     */
    private void setTitleEntityList() throws IllegalAccessException {
        if(param.getTempPath()!=null){
            return;
        }
        //传入表头
        if(param.getTitleEntityList()!=null){
            titleEntityList=ExportTitleUtil.getTitleList(param.getTitleEntityList(),null);
        }else{
            Field[] fields = param.getClz().getDeclaredFields();
            titleEntityList=ExportTitleUtil.getBeanTitleList(fields,dataList);
        }

    }




    private void setData() throws IllegalAccessException {
        int i=param.getStartRow();
        /*插入数据*/
        for (Object entity:dataList){
            HSSFRow rowNum = sheet.createRow(i);
            //rowNum.setHeight((short) 500);
            setDynamicCell(entity,rowNum, setCell(entity,rowNum));
            i++;
        }

        /*合并单元格*/
        List<ExcelRegionVo> regions=getRegionVoList();
        for (ExcelRegionVo regionVo : regions) {
            if (regionVo.getEndRow() > regionVo.getStarRow()
                    || regionVo.getEndCell() > regionVo.getStarCell()) {
                CellRangeAddress region = new CellRangeAddress(regionVo.getStarRow(), regionVo.getEndRow(), regionVo.getStarCell(), regionVo.getEndCell());
                sheet.addMergedRegion(region);
            }

        }
    }

    /**
     * 设置单元格
     * @param entity
     * @param rowNum
     */
    private int setCell(Object entity, HSSFRow rowNum)  {
        Field[] fields=param.getClz().getDeclaredFields();
        int result=param.getStartColumn();
        for(Field field:fields){
            field.setAccessible(true);
            ExcelField fieldAnnotation=field.getAnnotation(ExcelField.class);
            if(fieldAnnotation!=null){
                if(fieldAnnotation.sort()>-1){
                    Object value;
                    try {
                        value=field.get(entity);
                    }catch (Exception ex){
                        value="";
                    }

                    if(fieldAnnotation.wConvert()!=VoidConvertor.class){
                        try {

                            value=fieldAnnotation.wConvert().newInstance().writConvert(value,fieldAnnotation.wParam());
                        } catch (Exception ex) {
                            value="";
                        }
                    }
                    HSSFCell cell = rowNum.createCell(fieldAnnotation.sort()+param.getStartColumn());
                    cell.setCellValue(value!=null?value.toString():"");
                    //设置单元格样式
                    if(param.getTempPath()==null){
                        cell.setCellStyle(param.getCellStyle().getCellStyle((HSSFWorkbook) workbook));
                    }

                    /*合并行*/
                    if (fieldAnnotation.aotuRegion()) {
                        if(regionVoList==null){
                            regionVoList=new ArrayList<>();
                        }
                        ExcelRegionVo regionVo = new ExcelRegionVo();
                        regionVo.setFiledName(field.getName());
                        regionVo.setStarRow(rowNum.getRowNum());
                        /*未考虑合并列*/
                        regionVo.setStarCell(fieldAnnotation.sort()+param.getStartColumn());
                        regionVo.setEndCell(fieldAnnotation.sort()+param.getStartColumn());
                        regionVo.setValue(value!=null?value.toString():"");
                        regionVoList.add(regionVo);
                    }
                    result++;
                }
            }
        }
        return result;
    }

    /**
     * 设置动态列
     * @param entity
     * @param rowNum
     * @param cellNum
     */
    private void setDynamicCell(Object entity, HSSFRow rowNum,int cellNum) throws IllegalAccessException {
        Field[] fields = param.getClz().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            ExcelField fieldAnnotation = field.getAnnotation(ExcelField.class);
            if(fieldAnnotation==null){
                continue;
            }
            if (!fieldAnnotation.dynamic()){
                continue;
            }

            //处理动态列
            if (field.getType() == List.class) {
                Type genericType = field.getGenericType();
                if (genericType == null) {
                    continue;
                }
                if (genericType instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) genericType;
                    Class<?> genericClz = (Class<?>) pt.getActualTypeArguments()[0];
                    if (genericClz.getPackage().getName().startsWith("cn.zaichi.edu.")) {
                        List<?> list= (List<?>) field.get(entity);
                        Field[] dynamicFields = genericClz.getDeclaredFields();
                        for(Object dy:list){
                            String columnValue = null;
                            for (Field dynamicField : dynamicFields) {
                                dynamicField.setAccessible(true);
                                ExcelDynamicValue dynamicValueAnnotation = dynamicField.getAnnotation(ExcelDynamicValue.class);
                                if (dynamicValueAnnotation != null) {
                                    columnValue=dynamicField.get(dy).toString();
                                }
                            }
                            HSSFCell cell = rowNum.createCell(cellNum);
                            cell.setCellValue(columnValue);
                            //设置单元格样式
                            if(param.getTempPath()==null){
                                cell.setCellStyle(param.getCellStyle().getCellStyle((HSSFWorkbook) workbook));
                            }

                            cellNum++;
                        }
                    }
                }
            }
        }
    }
    /**
     * 合并单元格信息
     *
     * @return
     */
    private List<ExcelRegionVo> getRegionVoList() {
        List<ExcelRegionVo> list = new ArrayList<>();
        Map<String, ExcelRegionVo> starMap = new HashMap<>();
        Map<String, ExcelRegionVo> endMap = new HashMap<>();
        for (ExcelRegionVo vo : regionVoList) {
            String key = vo.getFiledName() + ":" + vo.getValue();
            if (starMap.get(key) == null) {
                starMap.put(key, vo);
                endMap.put(key, vo);
                continue;
            }
            if (starMap.get(key).getFiledName().equals(vo.getFiledName())
                    && starMap.get(key).getValue().equals(vo.getValue())) {
                if (starMap.get(key).getStarRow() > vo.getStarRow()) {
                    starMap.put(key, vo);

                } else {
                    endMap.put(key, vo);
                }
            }
        }

        for (String key : starMap.keySet()) {
            ExcelRegionVo vo = starMap.get(key);
            vo.setEndRow(endMap.get(key).getStarRow());
            list.add(vo);
        }
        return list;
    }



    /**
     * 追加sheet
     * @param param
     */
    public void append(BaseExportParam param) throws IllegalAccessException {
        this.param=param;
        this.sheet=ExportWorkbookUtil.getSheet(param,workbook);
        this.dataList=param.getDataList();
        regionVoList=new ArrayList<>();
        //设置表头数据
        setTitleEntityList();
        //创建表头
        ExportTitleUtil.setSheetTitle(param.getTitleStarRow(),titleEntityList,sheet,param,workbook);
        //设置数据
        setData();
    }

    /**
     * 返回工作簿
     * @return
     */
    public HSSFWorkbook getWorkbook(){
        return (HSSFWorkbook) this.workbook;
    }


}
